[CQOI2017]老C的方块

2020-01-20
CQOI

题意

在下图所示的方阵中,蓝边是挡板,按照一定的规律出现

有一些方格中放了方块,清除方块要一定代价,求最小的代价,使得以下的形状不出现

题解

先棋盘黑白染色,然后再按照是否与挡板相邻染成四色

重要发现:所有不喜欢的图形一定由四色各一种组成

建四层的图,跑网络最大流即可,因为最大流一定是所需的最小代价

调试记录

dfs的时候min(Max-flow,e[i].f),把已有的flow减掉!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <cstdio>
#include <queue>
#include <cstring>
#include <map>
#define MP make_pair
const int maxn = 5e5 + 5;
const int INF = 0x3f3f3f3f;
using namespace std;
struct E{
int to, nxt, f;
}e[maxn * 40];
int head[maxn], tot = 1;
void addedge(int u, int v, int f){
e[++tot].to = v, e[tot].nxt = head[u], e[tot].f = f;
head[u] = tot;
}
void ins(int u, int v, int f){
addedge(u, v, f); addedge(v, u, 0);
}
int S, T, dep[maxn];
bool bfs(){
queue <int> q; while (!q.empty()) q.pop();
q.push(S); memset(dep, 0, sizeof dep); dep[S] = 1;
while (!q.empty()){
int cur = q.front(); q.pop();
for (int i = head[cur]; i; i = e[i].nxt){
int v = e[i].to;
if (e[i].f == 0 || dep[v] != 0) continue;
dep[v] = dep[cur] + 1;
q.push(v);
}
}
return (dep[T] > 0);
}
int dfs(int cur, int Max){
if (cur == T) return Max;
int flow = 0;
for (int i = head[cur]; i; i = e[i].nxt){
int v = e[i].to;
if (flow >= Max) return Max;
if (e[i].f > 0 && dep[v] == dep[cur] + 1){
int tmp = dfs(v, min(Max - flow, e[i].f));
e[i].f -= tmp;
e[i ^ 1].f += tmp;
flow += tmp;
}
}
return flow;
}
int maxflow = 0;
void Dinic(){
while (bfs()) maxflow += dfs(S, INF);
}
map <pair<int, int>, int> lnk;
int L, C, n; int x[maxn], y[maxn], w[maxn];
int main(){
scanf("%d%d%d", &C, &L, &n);
for (int i = 1; i <= n; i++){
scanf("%d%d%d", x + i, y + i, w + i);
lnk[MP(x[i], y[i])] = i;
} S = n + 1, T = n + 2;
for (int i = 1; i <= n; i++){
if (x[i] % 4 == 0){
if (y[i] % 2 == 1) ins(S, i, w[i]);
else{
if (lnk[MP(x[i] + 1, y[i])]) ins(lnk[MP(x[i] + 1, y[i])], i, INF);
if (lnk[MP(x[i], y[i] + 1)]) ins(lnk[MP(x[i], y[i] + 1)], i, INF);
if (lnk[MP(x[i], y[i] - 1)]) ins(lnk[MP(x[i], y[i] - 1)], i, INF);
}
}
if (x[i] % 4 == 1){
if (y[i] % 2 == 0) ins(S, i, w[i]);
else{
if (lnk[MP(x[i], y[i] - 1)]) ins(lnk[MP(x[i], y[i] - 1)], i, INF);
if (lnk[MP(x[i], y[i] + 1)]) ins(lnk[MP(x[i], y[i] + 1)], i, INF);
if (lnk[MP(x[i] - 1, y[i])]) ins(lnk[MP(x[i] - 1, y[i])], i, INF);
if (lnk[MP(x[i] + 1, y[i])]) ins(i, lnk[MP(x[i] + 1, y[i])], min(w[i], w[lnk[MP(x[i] + 1, y[i])]]));
}
}
if (x[i] % 4 == 2){
if (y[i] % 2 == 1){
if (lnk[MP(x[i], y[i] - 1)]) ins(i, lnk[MP(x[i], y[i] - 1)], INF);
if (lnk[MP(x[i], y[i] + 1)]) ins(i, lnk[MP(x[i], y[i] + 1)], INF);
if (lnk[MP(x[i] + 1, y[i])]) ins(i, lnk[MP(x[i] + 1, y[i])], INF);
}
else ins(i, T, w[i]);
}
if (x[i] % 4 == 3){
if (y[i] % 2 == 0){
if (lnk[MP(x[i], y[i] - 1)]) ins(i, lnk[MP(x[i], y[i] - 1)], INF);
if (lnk[MP(x[i], y[i] + 1)]) ins(i, lnk[MP(x[i], y[i] + 1)], INF);
if (lnk[MP(x[i] - 1, y[i])]) ins(i, lnk[MP(x[i] - 1, y[i])], INF);
if (lnk[MP(x[i] + 1, y[i])]) ins(lnk[MP(x[i] + 1, y[i])], i, min(w[i], w[lnk[MP(x[i] + 1, y[i])]]));
}
else ins(i, T, w[i]);
}
}
Dinic();
printf("%d\n", maxflow);
return 0;
}